using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    public JObject frame_input = new JObject();
    public JObject frame_info = new JObject();

    public float move_speed = 2f;

    public GameObject look_at;
    public Camera player_camera;
    public GameObject camera_gameobject;
    public GameObject x_bot;
    public GameObject in_ground_obj;
    Animator animator;
    public GameManager gameManager;
    // Start is called before the first frame update
    void Start()
    {
        animator = x_bot.GetComponent<Animator>();
        if (gameManager.user != name)
        {
            camera_gameobject.SetActive(false);
        }
    }

    // Update is called once per frame
    void Update()
    {

    }

    void FixedUpdate()
    {
        if (gameManager.user == name)
        {
            LogicInput();
            InfoCollection();
        }

        ApplyFrameInput();
    }

    private void LogicInput()
    {
        float vertical = Input.GetAxis("Vertical");
        float horizontal = Input.GetAxis("Horizontal");

        frame_input["vertical"] = vertical;
        frame_input["horizontal"] = horizontal;

        // movement
        Vector3 velocity = Vector3.zero;
        velocity.z = (float)(Math.Cos(look_at.transform.localEulerAngles.y / 180 * Math.PI) * vertical) - (float)(Math.Sin(look_at.transform.localEulerAngles.y / 180 * Math.PI) * horizontal);
        velocity.x = (float)(Math.Sin(look_at.transform.localEulerAngles.y / 180 * Math.PI) * vertical) + (float)(Math.Cos(look_at.transform.localEulerAngles.y / 180 * Math.PI) * horizontal);
        if (Math.Pow(velocity.z, 2) + Math.Pow(velocity.x, 2) > 1)
        {
            velocity = velocity.normalized;
        }
        velocity *= move_speed;

        frame_input["velocity_x"] = velocity.x;
        frame_input["velocity_y"] = velocity.y;
        frame_input["velocity_z"] = velocity.z;
    }

    public void InfoCollection()
    {
        frame_info["position_x"] = transform.position.x;
        frame_info["position_y"] = transform.position.y;
        frame_info["position_z"] = transform.position.z;
        frame_info["rotation_x"] = look_at.transform.eulerAngles.x;
        frame_info["rotation_y"] = look_at.transform.eulerAngles.y;
        frame_info["rotation_z"] = look_at.transform.eulerAngles.z;
    }

    int frame_on_air = 0;
    private void ApplyFrameInput()
    {
        if (frame_input != null)
        {
            float vertical = (float)frame_input["vertical"];
            float horizontal = (float)frame_input["horizontal"];

            // movement
            Vector3 velocity = Vector3.zero;
            velocity.z = (float)(Math.Cos(look_at.transform.localEulerAngles.y / 180 * Math.PI) * vertical) - (float)(Math.Sin(look_at.transform.localEulerAngles.y / 180 * Math.PI) * horizontal);
            velocity.x = (float)(Math.Sin(look_at.transform.localEulerAngles.y / 180 * Math.PI) * vertical) + (float)(Math.Cos(look_at.transform.localEulerAngles.y / 180 * Math.PI) * horizontal);
            if (Math.Pow(velocity.z, 2) + Math.Pow(velocity.x, 2) > 1)
            {
                velocity = velocity.normalized;
            }
            velocity *= move_speed;
            if (in_ground_obj.GetComponent<PlayerInGround>().in_ground)
            {
                velocity.y = 0;
                frame_on_air = 0;
            }
            else
            {
                velocity.y = y_v(frame_on_air);
                frame_on_air++;
            }
            GetComponent<Rigidbody>().velocity = velocity;

            //身体旋转 动画
            if (velocity != Vector3.zero)
            {
                animator.SetBool("on_the_move", true);
                double vec_angle = Math.Atan(velocity.x / velocity.z);
                if (velocity.z < 0) vec_angle += Math.PI;
                float new_angle = (float)(vec_angle / Math.PI * 180);
                if (new_angle <= 0) new_angle += 360;
                float last_angle = x_bot.transform.localEulerAngles.y;
                Quaternion rotation;
                float rotation_speed = 0.2f;
                if (new_angle - last_angle > 180)
                {
                    rotation = Quaternion.Euler(0, last_angle + (new_angle - last_angle - 360) * rotation_speed, 0);
                }
                else
                {
                    if (new_angle - last_angle < -180)
                    {
                        rotation = Quaternion.Euler(0, last_angle + (new_angle - last_angle + 360) * rotation_speed, 0);
                    }
                    else
                    {
                        rotation = Quaternion.Euler(0, last_angle + (new_angle - last_angle) * rotation_speed, 0);
                    }
                }
                x_bot.transform.rotation = rotation;
            }
            else
            {
                animator.SetBool("on_the_move", false);
            }
        }
    }

    public void InfoSync()
    {
        Vector3 position = new Vector3(
            (float)frame_info["position_x"],
            (float)frame_info["position_y"],
            (float)frame_info["position_z"]);
        transform.position = position;

        Quaternion rotation = Quaternion.Euler(
            (float)frame_info["rotation_x"],
            (float)frame_info["rotation_y"],
            (float)frame_info["rotation_z"]);
        look_at.transform.rotation = rotation;
    }

    public float y_v(int x)
    {
        float y = -((float)x / 64 * 9.8f);
        if (y < -9.8f) y = -9.8f;
        return y;
    }
}
